/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package lucava.metamodel.uspeed.visitor;

import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import lucava.metamodel.uspeed.AttributeElement;
import lucava.metamodel.uspeed.ClassElement;
import lucava.metamodel.uspeed.MethodElement;
import lucava.metamodel.uspeed.ParameterElement;
import lucava.metamodel.uspeed.RelationElement;
import lucava.metamodel.uspeed.UspeedDocument;

/**
 *
 * @author glenn
 */
public class XmlVisitor extends AbstractElementVisitor {

    Element current;
    protected ArrayList<Element> classes = new ArrayList<Element>();

    public XmlVisitor() {
    }

    @Override
    public void enterDocument(UspeedDocument document) {
        
    }

    @Override
    public void leaveDocument(UspeedDocument document) {
    }

    @Override
    public void enterClass(ClassElement element) {



        current = new Element("class");
        addAttribute(current, "name", element.getName());


        Iterator<String> extIt = element.getExtendedClasses().iterator();
        while (extIt.hasNext()) {
            Element extNode = new Element("extends");
            addAttribute(extNode, "class", extIt.next());
            current.addContent(extNode);
        }


        Iterator<String> implIt = element.getImplementedClasses().iterator();
        while (implIt.hasNext()) {
            Element impNode = new Element("implements");
            addAttribute(impNode, "class", implIt.next());
            current.addContent(impNode);
        }


        Iterator<String> stereoIt = element.getStereotypes().iterator();
        while (stereoIt.hasNext()) {
            Element stNode = new Element("stereotype");
            addAttribute(stNode, "name", stereoIt.next());
            current.addContent(stNode);
        }

        Iterator<String> commIt = element.getComments().iterator();
        while (commIt.hasNext()) {
            Element commNode = new Element("comment");
            addAttribute(commNode, "text", commIt.next());
            current.addContent(commNode);
        }

        classes.add(current);


    }

    @Override
    public void enterAttribute(AttributeElement element) {
        Element attrNode = new Element("attribute");

        addAttribute(attrNode, "name", element.getName());
        addAttribute(attrNode, "type", element.getType());
        addAttribute(attrNode, "visibility", element.getVisibility());

        Iterator<String> commIt = element.getComments().iterator();
        while (commIt.hasNext()) {
            Element commNode = new Element("comment");
            addAttribute(commNode, "text", commIt.next());
            attrNode.addContent(commNode);
        }

        current.addContent(attrNode);

    }

    @Override
    public void enterMethod(MethodElement element) {
        Element methNode = new Element("method");

        addAttribute(methNode, "name", element.getName());
        addAttribute(methNode, "type", element.getType());
        addAttribute(methNode, "visibility", element.getVisibility());

        Iterator<String> commIt = element.getComments().iterator();
        while (commIt.hasNext()) {
            Element commNode = new Element("comment");
            addAttribute(commNode, "text", commIt.next());
            methNode.addContent(commNode);
        }

        current.addContent(methNode);
        current = methNode;
    }

    @Override
    public void leaveMethod(MethodElement element) {
        current = current.getParentElement();
    }

    @Override
    public void enterParameter(ParameterElement element) {
        Element paramNode = new Element("parameter");
        addAttribute(paramNode, "name", element.getName());
        addAttribute(paramNode, "type", element.getType());
        current.addContent(paramNode);
    }

    @Override
    public void enterRelation(RelationElement element) {
        Element relNode = new Element(element.getType());

        addAttribute(relNode, "name", element.getName());
        addAttribute(relNode, "type", element.getTargetClass());

        addAttribute(relNode, "sourceCard", element.getSourceCard());
        addAttribute(relNode, "targetCard", element.getTargetCard());
        addAttribute(relNode, "directional", element.isDirectional().toString());

        current.addContent(relNode);
    }

    protected void addAttribute(Element elmnt, String key, String value) {

        if (null != key && null != value) {
            elmnt.setAttribute(new Attribute(key, value));
        }

    }

    public Document buildDocument() {

        Element root = new Element("root");
        Document document = new Document(root);

        Iterator<Element> classIt = classes.iterator();
        while (classIt.hasNext()) {
            root.addContent(classIt.next());
        }

        return document;
    }

    public void export(String filename) {
        try {
            FileWriter writer = new FileWriter(filename);

            XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());
            outputter.output(buildDocument(), writer);
            writer.flush();
            writer.close();
        } catch (IOException ex) {

            System.err.println(ex.getMessage());
        }

    }
}
